package com.copd.service.impl;

import com.copd.service.DataBackupService;
import com.copd.service.DoctorOperationLogService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class DataBackupServiceImpl implements DataBackupService {
    
    private static final Logger logger = LoggerFactory.getLogger(DataBackupServiceImpl.class);
    
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    @Autowired
    private DoctorOperationLogService logService;
    
    @Override
    @Transactional
    public boolean backupPatientInfo(Integer patientId, Integer doctorId, String operationType) {
        try {
            if (patientId == null || doctorId == null) {
                logger.warn("备份患者信息失败：患者ID或医生ID为空");
                return false;
            }
            
            // 1. 查询患者信息
            String selectSql = "SELECT * FROM patient_info WHERE patient_id = ?";
            Map<String, Object> patientInfo = jdbcTemplate.queryForMap(selectSql, patientId);
            
            if (patientInfo == null || patientInfo.isEmpty()) {
                logger.warn("备份患者信息失败：未找到患者ID为{}的记录", patientId);
                return false;
            }
            
            // 2. 将患者信息插入备份表
            String insertSql = "INSERT INTO patient_info_backup (user_id, patient_id, name, gender, age, " +
                    "department, hospitalization_number, doctor_id, operation_type) " +
                    "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
            
            jdbcTemplate.update(insertSql,
                    patientInfo.get("user_id"),
                    patientInfo.get("patient_id"),
                    patientInfo.get("name"),
                    patientInfo.get("gender"),
                    patientInfo.get("age"),
                    patientInfo.get("department"),
                    patientInfo.get("hospitalization_number"),
                    doctorId,
                    operationType
            );
            
            // 3. 记录操作日志
            logPatientBackupOperation(doctorId, patientId, "patient_info", patientId, operationType);
            
            logger.info("成功备份患者ID为{}的基本信息", patientId);
            return true;
        } catch (Exception e) {
            logger.error("备份患者信息异常：", e);
            return false;
        }
    }
    
    @Override
    @Transactional
    public boolean backupDiagnosisRecord(Integer recordId, Integer patientId, Integer doctorId, String operationType) {
        try {
            if (recordId == null || patientId == null || doctorId == null) {
                logger.warn("备份诊断记录失败：记录ID、患者ID或医生ID为空");
                return false;
            }
            
            // 1. 查询诊断记录
            String selectSql = "SELECT * FROM diagnosis_records WHERE record_id = ?";
            Map<String, Object> diagnosisRecord = jdbcTemplate.queryForMap(selectSql, recordId);
            
            if (diagnosisRecord == null || diagnosisRecord.isEmpty()) {
                logger.warn("备份诊断记录失败：未找到记录ID为{}的诊断记录", recordId);
                return false;
            }
            
            // 2. 将诊断记录插入备份表
            String insertSql = "INSERT INTO diagnosis_records_backup (record_id, patient_id, diagnosis_item, " +
                    "diagnosis_content, remarks, diagnosis_date, doctor_id, operation_type) " +
                    "VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
            
            jdbcTemplate.update(insertSql,
                    diagnosisRecord.get("record_id"),
                    diagnosisRecord.get("patient_id"),
                    diagnosisRecord.get("diagnosis_item"),
                    diagnosisRecord.get("diagnosis_content"),
                    diagnosisRecord.get("remarks"),
                    diagnosisRecord.get("diagnosis_date"),
                    doctorId,
                    operationType
            );
            
            // 3. 记录操作日志
            logPatientBackupOperation(doctorId, patientId, "diagnosis_records", recordId, operationType);
            
            logger.info("成功备份记录ID为{}的诊断记录", recordId);
            return true;
        } catch (Exception e) {
            logger.error("备份诊断记录异常：", e);
            return false;
        }
    }
    
    @Override
    @Transactional
    public boolean backupExaminationItem(Integer examId, Integer patientId, Integer doctorId, String operationType) {
        try {
            if (examId == null || patientId == null || doctorId == null) {
                logger.warn("备份检查项目失败：检查ID、患者ID或医生ID为空");
                return false;
            }
            
            // 1. 查询检查项目
            String selectSql = "SELECT * FROM examination_items WHERE exam_id = ?";
            Map<String, Object> examinationItem = jdbcTemplate.queryForMap(selectSql, examId);
            
            if (examinationItem == null || examinationItem.isEmpty()) {
                logger.warn("备份检查项目失败：未找到检查ID为{}的检查项目", examId);
                return false;
            }
            
            // 2. 将检查项目插入备份表
            String insertSql = "INSERT INTO examination_items_backup (exam_id, patient_id, exam_category, " +
                    "exam_item, exam_result, reference_value, remarks, exam_date, doctor_id, operation_type) " +
                    "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
            
            jdbcTemplate.update(insertSql,
                    examinationItem.get("exam_id"),
                    examinationItem.get("patient_id"),
                    examinationItem.get("exam_category"),
                    examinationItem.get("exam_item"),
                    examinationItem.get("exam_result"),
                    examinationItem.get("reference_value"),
                    examinationItem.get("remarks"),
                    examinationItem.get("exam_date"),
                    doctorId,
                    operationType
            );
            
            // 3. 记录操作日志
            logPatientBackupOperation(doctorId, patientId, "examination_items", examId, operationType);
            
            logger.info("成功备份检查ID为{}的检查项目", examId);
            return true;
        } catch (Exception e) {
            logger.error("备份检查项目异常：", e);
            return false;
        }
    }
    
    @Override
    @Transactional
    public boolean backupTreatmentPlan(Integer planId, Integer patientId, Integer doctorId, String operationType) {
        try {
            if (planId == null || patientId == null || doctorId == null) {
                logger.warn("备份治疗方案失败：方案ID、患者ID或医生ID为空");
                return false;
            }
            
            // 1. 查询治疗方案
            String selectSql = "SELECT * FROM treatment_plans WHERE plan_id = ?";
            Map<String, Object> treatmentPlan = jdbcTemplate.queryForMap(selectSql, planId);
            
            if (treatmentPlan == null || treatmentPlan.isEmpty()) {
                logger.warn("备份治疗方案失败：未找到方案ID为{}的治疗方案", planId);
                return false;
            }
            
            // 2. 将治疗方案插入备份表
            String insertSql = "INSERT INTO treatment_plans_backup (plan_id, patient_id, plan_category, " +
                    "treatment_item, specific_plan, remarks, plan_date, doctor_id, operation_type) " +
                    "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
            
            jdbcTemplate.update(insertSql,
                    treatmentPlan.get("plan_id"),
                    treatmentPlan.get("patient_id"),
                    treatmentPlan.get("plan_category"),
                    treatmentPlan.get("treatment_item"),
                    treatmentPlan.get("specific_plan"),
                    treatmentPlan.get("remarks"),
                    treatmentPlan.get("plan_date"),
                    doctorId,
                    operationType
            );
            
            // 3. 记录操作日志
            logPatientBackupOperation(doctorId, patientId, "treatment_plans", planId, operationType);
            
            logger.info("成功备份方案ID为{}的治疗方案", planId);
            return true;
        } catch (Exception e) {
            logger.error("备份治疗方案异常：", e);
            return false;
        }
    }
    
    @Override
    @Transactional
    public boolean backupDischargeRecord(Integer dischargeId, Integer patientId, Integer doctorId, String operationType) {
        try {
            if (dischargeId == null || patientId == null || doctorId == null) {
                logger.warn("备份出院建议失败：建议ID、患者ID或医生ID为空");
                return false;
            }
            
            // 1. 查询出院建议
            String selectSql = "SELECT * FROM discharge_records WHERE discharge_id = ?";
            Map<String, Object> dischargeRecord = jdbcTemplate.queryForMap(selectSql, dischargeId);
            
            if (dischargeRecord == null || dischargeRecord.isEmpty()) {
                logger.warn("备份出院建议失败：未找到建议ID为{}的出院建议", dischargeId);
                return false;
            }
            
            // 2. 将出院建议插入备份表
            String insertSql = "INSERT INTO discharge_records_backup (discharge_id, patient_id, advice_category, " +
                    "discharge_item, discharge_content, remarks, advice_date, doctor_id, operation_type) " +
                    "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
            
            jdbcTemplate.update(insertSql,
                    dischargeRecord.get("discharge_id"),
                    dischargeRecord.get("patient_id"),
                    dischargeRecord.get("advice_category"),
                    dischargeRecord.get("discharge_item"),
                    dischargeRecord.get("discharge_content"),
                    dischargeRecord.get("remarks"),
                    dischargeRecord.get("advice_date"),
                    doctorId,
                    operationType
            );
            
            // 3. 记录操作日志
            logPatientBackupOperation(doctorId, patientId, "discharge_records", dischargeId, operationType);
            
            logger.info("成功备份建议ID为{}的出院建议", dischargeId);
            return true;
        } catch (Exception e) {
            logger.error("备份出院建议异常：", e);
            return false;
        }
    }
    
    @Override
    @Transactional
    public boolean backupByTableAndId(String tableName, Integer recordId, Integer patientId, Integer doctorId, String operationType) {
        if (tableName == null || recordId == null) {
            logger.warn("备份数据失败：表名或记录ID为空");
            return false;
        }
        
        switch (tableName) {
            case "patient_info":
                return backupPatientInfo(recordId, doctorId, operationType);
            case "diagnosis_records":
                return backupDiagnosisRecord(recordId, patientId, doctorId, operationType);
            case "examination_items":
                return backupExaminationItem(recordId, patientId, doctorId, operationType);
            case "treatment_plans":
                return backupTreatmentPlan(recordId, patientId, doctorId, operationType);
            case "discharge_records":
                return backupDischargeRecord(recordId, patientId, doctorId, operationType);
            default:
                logger.warn("备份数据失败：不支持的表名 {}", tableName);
                return false;
        }
    }
    
    /**
     * 记录患者备份操作日志
     */
    private void logPatientBackupOperation(Integer doctorId, Integer patientId, String tableName, 
                                          Integer recordId, String operationType) {
        try {
            // 构建备份操作详情
            Map<String, Object> backupDetail = new HashMap<>();
            backupDetail.put("tableName", tableName);
            backupDetail.put("recordId", recordId);
            backupDetail.put("operationType", operationType);
            backupDetail.put("backupTime", System.currentTimeMillis());
            
            // 转为JSON字符串
            String detailJson = new com.fasterxml.jackson.databind.ObjectMapper().writeValueAsString(backupDetail);
            
            // 记录备份操作日志
            logService.logPatientOperation(
                doctorId,
                patientId,
                "备份",
                null, // IP地址（自动获取）
                null, // 设备信息（自动获取）
                true,
                null,
                tableName + "_backup",
                recordId,
                detailJson
            );
        } catch (Exception e) {
            logger.error("记录备份操作日志失败", e);
        }
    }
    
    /**
     * 查询备份数据
     */
    @Override
    public Map<String, Object> queryBackupData(com.copd.dto.BackupDataQueryRequest request, Integer doctorId) {
        if (request == null) {
            throw new IllegalArgumentException("查询请求不能为空");
        }
        
        Map<String, Object> result = new HashMap<>();
        result.put("page", request.getPage());
        result.put("size", request.getSize());
        
        // 构建查询条件
        StringBuilder queryBuilder = new StringBuilder();
        List<Object> params = new ArrayList<>();
        
        // 基本查询SQL
        queryBuilder.append("SELECT * FROM ");
        
        // 根据表名确定查询哪个备份表
        String tableName = request.getTableName();
        if (tableName != null && !tableName.isEmpty()) {
            queryBuilder.append(tableName);
        } else {
            // 默认查询患者基本信息备份表
            queryBuilder.append("patient_info_backup");
        }
        
        // 构建WHERE条件
        queryBuilder.append(" WHERE 1=1");
        
        // 患者ID条件
        if (request.getPatientId() != null) {
            queryBuilder.append(" AND patient_id = ?");
            params.add(request.getPatientId());
        }
        
        // 操作类型条件
        if (request.getOperationType() != null && !request.getOperationType().isEmpty()) {
            queryBuilder.append(" AND operation_type = ?");
            params.add(request.getOperationType());
        }
        
        // 时间范围条件
        if (request.getStartTime() != null && !request.getStartTime().isEmpty()) {
            queryBuilder.append(" AND operation_time >= ?");
            params.add(request.getStartTime());
        }
        
        if (request.getEndTime() != null && !request.getEndTime().isEmpty()) {
            queryBuilder.append(" AND operation_time <= ?");
            params.add(request.getEndTime());
        }
        
        // 添加医生ID条件
        if (doctorId != null) {
            queryBuilder.append(" AND doctor_id = ?");
            params.add(doctorId);
        }
        
        // 构建计数SQL
        String countSql = "SELECT COUNT(*) FROM (" + queryBuilder.toString() + ") AS count_query";
        
        // 添加排序
        queryBuilder.append(" ORDER BY operation_time DESC");
        
        // 添加分页
        queryBuilder.append(" LIMIT ? OFFSET ?");
        params.add(request.getSize());
        params.add((request.getPage() - 1) * request.getSize());
        
        // 执行查询
        List<Map<String, Object>> backupData;
        try {
            backupData = jdbcTemplate.queryForList(queryBuilder.toString(), params.toArray());
            
            // 获取总数
            Integer total = jdbcTemplate.queryForObject(countSql, Integer.class, params.toArray());
            
            // 设置结果
            result.put("data", backupData);
            result.put("total", total != null ? total : 0);
            
            return result;
        } catch (Exception e) {
            logger.error("查询备份数据失败", e);
            throw new RuntimeException("查询备份数据失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取备份表信息
     */
    @Override
    public Map<String, Object> getBackupTablesInfo(Integer doctorId) {
        Map<String, Object> result = new HashMap<>();
        List<Map<String, Object>> backupTables = new ArrayList<>();
        
        // 添加各备份表信息
        Map<String, Object> patientInfoBackup = new HashMap<>();
        patientInfoBackup.put("tableName", "patient_info_backup");
        patientInfoBackup.put("description", "患者基本信息备份表");
        patientInfoBackup.put("count", countBackupRecords("patient_info_backup", doctorId));
        backupTables.add(patientInfoBackup);
        
        Map<String, Object> diagnosisRecordsBackup = new HashMap<>();
        diagnosisRecordsBackup.put("tableName", "diagnosis_records_backup");
        diagnosisRecordsBackup.put("description", "患者诊断记录备份表");
        diagnosisRecordsBackup.put("count", countBackupRecords("diagnosis_records_backup", doctorId));
        backupTables.add(diagnosisRecordsBackup);
        
        Map<String, Object> examinationItemsBackup = new HashMap<>();
        examinationItemsBackup.put("tableName", "examination_items_backup");
        examinationItemsBackup.put("description", "检查项目记录备份表");
        examinationItemsBackup.put("count", countBackupRecords("examination_items_backup", doctorId));
        backupTables.add(examinationItemsBackup);
        
        Map<String, Object> treatmentPlansBackup = new HashMap<>();
        treatmentPlansBackup.put("tableName", "treatment_plans_backup");
        treatmentPlansBackup.put("description", "治疗项目记录备份表");
        treatmentPlansBackup.put("count", countBackupRecords("treatment_plans_backup", doctorId));
        backupTables.add(treatmentPlansBackup);
        
        Map<String, Object> dischargeRecordsBackup = new HashMap<>();
        dischargeRecordsBackup.put("tableName", "discharge_records_backup");
        dischargeRecordsBackup.put("description", "出院建议记录备份表");
        dischargeRecordsBackup.put("count", countBackupRecords("discharge_records_backup", doctorId));
        backupTables.add(dischargeRecordsBackup);
        
        result.put("backupTables", backupTables);
        return result;
    }
    
    /**
     * 统计备份表中的记录数
     */
    private int countBackupRecords(String tableName, Integer doctorId) {
        try {
            String sql = "SELECT COUNT(*) FROM " + tableName;
            if (doctorId != null) {
                sql += " WHERE doctor_id = ?";
                return jdbcTemplate.queryForObject(sql, Integer.class, doctorId);
            } else {
                return jdbcTemplate.queryForObject(sql, Integer.class);
            }
        } catch (Exception e) {
            logger.warn("统计表{}的记录数失败: {}", tableName, e.getMessage());
            return 0;
        }
    }
    
    /**
     * 获取患者信息
     */
    @Override
    public Map<String, Object> getPatientInfo(Integer patientId) {
        if (patientId == null) {
            throw new IllegalArgumentException("患者ID不能为空");
        }
        
        try {
            String sql = "SELECT * FROM patient_info WHERE patient_id = ?";
            Map<String, Object> patientInfo = jdbcTemplate.queryForMap(sql, patientId);
            
            // 添加备份记录统计
            patientInfo.put("diagnosisBackupCount", countPatientBackupRecords("diagnosis_records_backup", patientId));
            patientInfo.put("examinationBackupCount", countPatientBackupRecords("examination_items_backup", patientId));
            patientInfo.put("treatmentBackupCount", countPatientBackupRecords("treatment_plans_backup", patientId));
            patientInfo.put("dischargeBackupCount", countPatientBackupRecords("discharge_records_backup", patientId));
            
            return patientInfo;
        } catch (Exception e) {
            logger.error("获取患者信息失败", e);
            throw new RuntimeException("获取患者信息失败: " + e.getMessage());
        }
    }
    
    /**
     * 统计患者备份记录数
     */
    private int countPatientBackupRecords(String tableName, Integer patientId) {
        try {
            String sql = "SELECT COUNT(*) FROM " + tableName + " WHERE patient_id = ?";
            return jdbcTemplate.queryForObject(sql, Integer.class, patientId);
        } catch (Exception e) {
            logger.warn("统计患者{}在表{}中的备份记录数失败: {}", patientId, tableName, e.getMessage());
            return 0;
        }
    }
    
    /**
     * 获取医生信息
     */
    @Override
    public Map<String, Object> getDoctorInfo(Integer doctorId) {
        if (doctorId == null) {
            throw new IllegalArgumentException("医生ID不能为空");
        }
        
        try {
            String sql = "SELECT user_id, username, name, contact_info, department, title, years_of_experience, certification, role " +
                         "FROM users WHERE user_id = ? AND role = 'doctor'";
            Map<String, Object> doctorInfo = jdbcTemplate.queryForMap(sql, doctorId);
            
            // 添加备份操作统计
            String countSql = "SELECT COUNT(*) FROM doctor_operation_log WHERE doctor_id = ? AND operation_type = '备份'";
            Integer backupCount = jdbcTemplate.queryForObject(countSql, Integer.class, doctorId);
            doctorInfo.put("backupOperationCount", backupCount != null ? backupCount : 0);
            
            return doctorInfo;
        } catch (Exception e) {
            logger.error("获取医生信息失败", e);
            throw new RuntimeException("获取医生信息失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取备份操作日志
     */
    @Override
    public Map<String, Object> getBackupOperationLogs(Integer doctorId, Integer patientId, String tableName, 
                                                    String operationType, String startTime, String endTime, 
                                                    Integer page, Integer size) {
        // 验证分页参数
        if (page == null || page < 1) {
            page = 1;
        }
        if (size == null || size < 1 || size > 100) {
            size = 10;
        }
        
        Map<String, Object> result = new HashMap<>();
        result.put("page", page);
        result.put("size", size);
        
        try {
            // 构建查询SQL和参数
            StringBuilder sql = new StringBuilder();
            List<Object> params = new ArrayList<>();
            
            sql.append("SELECT l.log_id, l.doctor_id, l.patient_id, l.operation_type, l.operation_time, ");
            sql.append("l.ip_address, l.device_info, l.operation_result, l.failure_reason, ");
            sql.append("d.detail_id, d.table_name, d.record_id, d.operation_detail, ");
            sql.append("u.username as doctor_name, p.name as patient_name ");
            sql.append("FROM doctor_operation_log l ");
            sql.append("LEFT JOIN doctor_operation_detail d ON l.log_id = d.log_id ");
            sql.append("LEFT JOIN users u ON l.doctor_id = u.user_id ");
            sql.append("LEFT JOIN patient_info p ON l.patient_id = p.patient_id ");
            sql.append("WHERE l.operation_type = '备份' ");
            
            // 按医生ID筛选
            if (doctorId != null) {
                sql.append("AND l.doctor_id = ? ");
                params.add(doctorId);
            }
            
            // 按患者ID筛选
            if (patientId != null) {
                sql.append("AND l.patient_id = ? ");
                params.add(patientId);
            }
            
            // 按表名筛选
            if (tableName != null && !tableName.isEmpty()) {
                sql.append("AND d.table_name LIKE ? ");
                params.add("%" + tableName + "%");
            }
            
            // 按操作类型筛选
            if (operationType != null && !operationType.isEmpty()) {
                sql.append("AND l.operation_type = ? ");
                params.add(operationType);
            }
            
            // 按时间范围筛选
            if (startTime != null && !startTime.isEmpty()) {
                sql.append("AND l.operation_time >= ? ");
                params.add(startTime);
            }
            
            if (endTime != null && !endTime.isEmpty()) {
                sql.append("AND l.operation_time <= ? ");
                params.add(endTime);
            }
            
            // 构建计数SQL
            String countSql = "SELECT COUNT(*) FROM (" + sql.toString() + ") AS count_query";
            
            // 添加排序
            sql.append("ORDER BY l.operation_time DESC ");
            
            // 添加分页
            sql.append("LIMIT ? OFFSET ?");
            params.add(size);
            params.add((page - 1) * size);
            
            // 执行查询
            List<Map<String, Object>> logs = jdbcTemplate.queryForList(sql.toString(), params.toArray());
            
            // 执行计数查询
            Integer total = jdbcTemplate.queryForObject(countSql, Integer.class, params.toArray());
            
            result.put("logs", logs);
            result.put("total", total != null ? total : 0);
            
            return result;
        } catch (Exception e) {
            logger.error("获取备份操作日志失败", e);
            throw new RuntimeException("获取备份操作日志失败: " + e.getMessage());
        }
    }
} 